#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdint.h>
#include "fpga_addr_define.h"
#include "debug.h"


#define FPGA_DEV "/dev/mem"


struct fpga_info_type
{
    short* fpga_head;    /* mem pointer head */
    int fd;              /* file fd */
};


static struct fpga_info_type g_fpga_info =
{
    .fpga_head = NULL,
    .fd = -1,
};


/**
 * @brief 初始化FPGA
 */
int FpgaInf_Init(void)
{
    struct fpga_info_type *pFpgaInfo = &g_fpga_info;
    int fd;
    unsigned short* mem_pointer;
    /* FPGA在内存中的映射区域大小 */
    size_t alloc_mem_size = 1024;
    /* FPGA在内存中的偏移地址 */
    off_t offset = 0x10000000;

    fd = open(FPGA_DEV, O_RDWR | O_SYNC);
    if(fd < 0)
    {
        PRINT_ERROR("Init FPGA FAILED.Can't Open %s !!!", FPGA_DEV);
        return -1;
    }

    pFpgaInfo->fd = fd;

    mem_pointer = (unsigned short*) mmap(NULL, alloc_mem_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset); 
    pFpgaInfo->fpga_head = (short*)mem_pointer;

    PRINT_INFO("Success");

    return 0;
}


/**
 * @brief 反向初始化FPGA
 */
int FpgaInf_Uninit(void)
{
    struct fpga_info_type *pFpgaInfo = &g_fpga_info;

    close(pFpgaInfo->fd);

    PRINT_INFO("Success");
    return 0;
}


/**
 * @brief 读FPGA
 */
int FpgaInf_Read(uint32_t addr, uint16_t *pValue)
{
    struct fpga_info_type *pFpgaInfo = &g_fpga_info;

    if(addr >= FPGA_ADDR_MAX)
    {
        PRINT_WARN("addr[%d]", addr);
        return -1;
    }

    *pValue = (uint16_t)(pFpgaInfo->fpga_head[addr]);
    return 0;
}


/**
 * @brief 写FPGA
 */
int FpgaInf_Write(uint32_t addr, uint16_t value)
{
    struct fpga_info_type *pFpgaInfo = &g_fpga_info;

    if(addr >= FPGA_ADDR_MAX / 2)
    {
        PRINT_WARN("addr[%d]", addr);
        return -1;
    }

    pFpgaInfo->fpga_head[addr] = (short)value;
    pFpgaInfo->fpga_head[254] = (short)(~value);

    return 0;
}

